function boom() {
    let bgLayer;
    {
        let canvas2 = document.getElementById('_canvas2');
        let ctx2 = canvas2.getContext('2d');
        bgLayer = new Layer(ctx2);
        bgLayer.name = 'bgLayer';
        bgLayer.interval = 5000;
        let bgImg;
        bgLayer.preload = function (loader) {
            bgImg = loader.loadImage('assets/images/Background.jpg');
        }
        bgLayer.create = function () {
            let bg = new BackgroundObject();
            bg.setImage(bgImg);
            bg.fillType = FILL_TYPE_TILE;
            bgLayer.addObject(bg);
        }
    }

    let canvas = document.getElementById("_canvas");
    let ctx = canvas.getContext("2d");
    let engine = new Engine(ctx);
    let layer = new Layer(ctx);

    let shotAudio;
    let boomAudio;
    let explosionObjects = [];
    layer.preload = function (loader) {
        shotAudio = loader.loadAudio('assets/sounds/shot.ogg');
        shotAudio.volume = 0.1;
        boomAudio = loader.loadAudio('assets/sounds/boom.mp3');
        boomAudio.volume = 0.1;

        ExplosionObject.explosionImages = loader.loadImageSet([
            'assets/images/Explosion_Sequence_A 1.png',
            'assets/images/Explosion_Sequence_A 2.png',
            'assets/images/Explosion_Sequence_A 3.png',
            'assets/images/Explosion_Sequence_A 4.png',
            'assets/images/Explosion_Sequence_A 5.png',
            'assets/images/Explosion_Sequence_A 6.png',
            'assets/images/Explosion_Sequence_A 7.png',
            'assets/images/Explosion_Sequence_A 8.png',
            'assets/images/Explosion_Sequence_A 9.png',
            'assets/images/Explosion_Sequence_A 10.png',
            'assets/images/Explosion_Sequence_A 11.png',
            'assets/images/Explosion_Sequence_A 12.png',
            'assets/images/Explosion_Sequence_A 13.png',
            'assets/images/Explosion_Sequence_A 14.png',
            'assets/images/Explosion_Sequence_A 15.png',
            'assets/images/Explosion_Sequence_A 16.png',
            'assets/images/Explosion_Sequence_A 17.png',
            'assets/images/Explosion_Sequence_A 18.png',
            'assets/images/Explosion_Sequence_A 19.png',
            'assets/images/Explosion_Sequence_A 20.png',
            'assets/images/Explosion_Sequence_A 21.png',
            'assets/images/Explosion_Sequence_A 22.png',
            'assets/images/Explosion_Sequence_A 23.png',
            'assets/images/Explosion_Sequence_A 24.png',
            'assets/images/Explosion_Sequence_A 25.png',
            'assets/images/Explosion_Sequence_A 26.png',
            'assets/images/Explosion_Sequence_A 27.png',
        ]);
    }

    layer.create = function () {
        let coordinate = new CoordinateObject();
        layer.addObject(coordinate);
        let player = new Player(layer);
        player.owner.position = new Position(400, 300);
        player.owner.speed = 50;

        for (let i = 1; i <= 5; i++) {
            let enemy = new EnemyRect(layer);
            enemy.owner.position = new Position(100 * i, 100);
            if (i % 2 == 0) {
                enemy.owner.addComponent(new GameComponent.LookAtMouse());
            } else {
                enemy.owner.addComponent(new GameComponent.LookAtObject(player.owner));
                enemy.owner.update = function () {
                    if (this.y < this.ctx.canvas.height * 2 / 3) {
                        this.y += 2;
                    }
                }
            }
        }
        let ball1 = new EnemyRect(layer);
        ball1.owner.width = 50;
        ball1.owner.height = 50;
        ball1.owner.position = new Position(200, 200);
        ball1.owner.autoDestory = false;
        ball1.owner.addComponent(new GameComponent.Surround(player.owner, 10));


        let ball2 = new BallArc(layer);
        ball2.owner.radius = 15;
        ball2.owner.position = new Position(300, 300);
        ball2.owner.name = 'test';
        ball2.owner.autoDestory = false;
        ball2.owner.addComponent(new GameComponent.Surround(ball1.owner, 30));

        let ball3 = new BallArc(layer);
        ball3.owner.position = new Position(300, 250);
        ball3.owner.name = 'test';
        ball3.owner.autoDestory = false;
        ball3.owner.addComponent(new GameComponent.Surround(ball2.owner, 50));

        let shotEnemy = new EnemyShotRect(layer);
        shotEnemy.owner.position = new Position(400, 200);
        shotEnemy.gun.name = 'gun';
        shotEnemy.gun.addComponent(new GameComponent.LookAtObject(player.owner));
    }
    engine.addLayer(bgLayer);
    engine.addLayer(layer);
    engine.run();

    /**
     * 爆炸对象
     */
    function ExplosionObject(layer) {
        var explosion = new SpriteObject();
        this.owner = explosion;
        this.owner.autoDestory = false;
        explosion.setImageSet(ExplosionObject.explosionImages);
        explosion.ready = function () {
            explosion.x -= explosion.width / 2;
            explosion.y -= explosion.height / 2;
        };
        let me = this;
        explosion.play();
        explosion.onAnimateFinish = function () {
            explosion.working = false;
            me.destory = true;
        }
        layer.addObject(explosion);
    }

    function Player(layer) {
        var _player = new SpriteObject();
        _player.name = 'player';
        this.owner = _player;
        _player.loadImage('assets/images/aaguntopdown.png');
        _player.autoDestory = false;
        _player.addComponent(new GameComponent.LookAtMouse());
        _player.addComponent(new GameComponent.WSADMove(20));
        _player.addComponent(new GameComponent.Shot(function () {
            var bullet = new Bullet(layer);
            bullet.name = 'player_' + bullet.owner.name;
            bullet.owner.direction = _player.direction;
            return bullet.owner;
        }, function () {
            return Input.mouse_down_check('left');
        }, 100, 10));
        layer.addObject(_player);
    }

    function EnemyRect(layer) {
        let enemy = new RectObject();
        this.owner = enemy;
        enemy.width = 50;
        enemy.height = 50;
        enemy.position = new Position(100, 100);
        layer.addObject(enemy);
    }

    function Bullet(layer) {
        let bullet = new ArcObject(5);
        this.owner = bullet;
        shotAudio.currentTime = 0;
        shotAudio.play();
        bullet.autoDestory = true;
        bullet.name = 'bullet_' + Bullet.count++;
        let shaker = new GameComponent.Shake();
        layer.addObject(shaker);
        function boomHandler() {
            boomAudio.currentTime = 0;
            boomAudio.play();
            var explosion;
            for (const exp of explosionObjects) {
                if (exp.destory) {
                    console.log('回收一个爆炸对象');
                    explosion = exp;
                    explosion.destory = false;
                    explosion.owner.reset();
                    explosion.owner.working = true;
                    break;
                }
            }
            if (!explosion) {
                explosion = new ExplosionObject(layer);
                explosion.owner.name = 'explosion';
                if (explosionObjects.length < 10) {
                    //最多缓存100个爆炸对象
                    explosionObjects.push(explosion);
                }
                explosion.owner.x = bullet.x;
                explosion.owner.y = bullet.y;
            } else {
                explosion.owner.x = bullet.x;
                explosion.owner.y = bullet.y;
                explosion.owner.ready();
            }
            bullet.destory();
            shaker.shake();
            shaker.count = 1;
            shaker.shakeFinish = function () {
                if (shaker.count < 2) {
                    shaker.count++;
                    shaker.shake();
                }
            }
        }
        layer.addObject(bullet);
        bullet.addCollisionEvent(RectObject, boomHandler);
    }
    Bullet.count = 1;

    function EnemyShotRect(layer) {
        let all = new GroupObject();
        let enemy = new RectObject();
        this.owner = all;
        enemy.width = 100;
        enemy.height = 80;

        let _gun = new RectObject();
        _gun.name = 'gun';
        this.gun = _gun;
        _gun.width = 200;
        _gun.height = 30;
        _gun.x = enemy._centerX - _gun.height / 2;
        _gun.y = enemy._centerY - _gun.height / 2;
        _gun.rotateCenterX = -_gun.width / 2 + _gun.height / 2;
        _gun.addComponent(new GameComponent.Shot(function () {
            var bullet = new ArcObject(5);
            bullet.autoDestory = true;
            bullet.direction = _gun.direction;
            return bullet;
        }, function () {
            return true;
        }, 50, 15));

        all.addObject(enemy);
        all.addObject(_gun);
        layer.addObject(enemy);
        layer.addObject(_gun);
        layer.addObject(all);
    }

    return engine;
}

